package problems;

public abstract class Problem<T> {
	private T result;
	private long timeTaken = -1L;
	
	public abstract void run();
	public void init() {
		// Nothing to do, usually
	}

	public final void runTimed() {
		init();
		
		long start = System.currentTimeMillis();
		run();
		timeTaken = System.currentTimeMillis() - start;
		
		if (result == null) {
			throw new IllegalStateException("run() did not set result");
		}
		assert timeTaken >= 0L;
	}
	
	public final T getResult() {
		if (result == null) {
			throw new IllegalStateException("Result not set");
		}
		return result;
	}
	
	public final void setResult(T result) {
		if (this.result != null) {
			throw new IllegalStateException("Result already set");
		}
		if (result == null) {
			throw new NullPointerException();
		}
		this.result = result;
	}
	
	public final boolean isFinished() {
		return result != null;
	}
	
	public final long getTimeTaken() {
		if (timeTaken == -1L) {
			throw new IllegalStateException("Not finished, or not timed");
		}
		return timeTaken;
	}
	
	public final void printResult() {
		if (timeTaken == -1L) {
			System.out.printf("Result for %s is %s", getName(), getResult().toString());
		}
		else {
			System.out.printf("Result for %s is %s in %d ms", getName(), getResult().toString(), getTimeTaken());
		}
	}
	
	public String getName() {
		return getClass().getSimpleName();
	}
}
